package com.proscenic.ops.common.filter;

import lombok.extern.slf4j.Slf4j;
import org.springframework.core.Ordered;
import org.springframework.util.AntPathMatcher;
import org.springframework.util.ObjectUtils;
import org.springframework.web.filter.OncePerRequestFilter;
import org.springframework.web.util.ContentCachingRequestWrapper;
import org.springframework.web.util.ContentCachingResponseWrapper;
import org.springframework.web.util.WebUtils;

import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Enumeration;
import java.util.regex.Pattern;

/**
 * @version 1.0
 * created by chenxin on 2021/9/22 19:38
 */
@Slf4j
public class LogFilter extends OncePerRequestFilter implements Ordered {
    private static final Pattern pattern = Pattern.compile("\\s*|\t|\r|\n");

    // put filter at the end of all other filters to make sure we are processing after all others
    private int order = Ordered.LOWEST_PRECEDENCE - 8;
    private String[] excludedUris;

    @Override
    public int getOrder() {
        return order;
    }

    @Override
    protected void initFilterBean() throws ServletException {
        FilterConfig filterConfig = super.getFilterConfig();
        String param = filterConfig.getInitParameter("excludedUris");
        if (!ObjectUtils.isEmpty(param)) {
            this.excludedUris = param.split(",");
        }
    }

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response,
                                    FilterChain filterChain) throws ServletException, IOException {
        String uri = request.getRequestURI();
        AntPathMatcher matcher = new AntPathMatcher();
        for(String excludedUri : excludedUris){
            if(matcher.match(excludedUri, uri)){
                filterChain.doFilter(request, response);
                return;
            }
        }

        log.info("------------start------------");
        log.info("request uri:{}", request.getRequestURI());
        log.info("request method:{}", request.getMethod());

        String token = request.getHeader("token");
        log.info("request Header token:{}", token);

        String params = getRequestParams(request);
        log.info("request params:[{}]", params);

        long beginTime = System.currentTimeMillis();
        ContentCachingRequestWrapper wrapperRequest = new ContentCachingRequestWrapper(request);
        ContentCachingResponseWrapper wrapperResponse = new ContentCachingResponseWrapper(response);
        filterChain.doFilter(wrapperRequest, wrapperResponse);
        long endTime = System.currentTimeMillis();

        String requestBodyStr = getRequestBody(wrapperRequest);
        log.info("request body:{}", requestBodyStr);

//        String responseBodyStr = getResponseBody(wrapperResponse);
//        log.info("response body:{}", responseBodyStr);

        log.info("request time:{} ", endTime - beginTime);
        log.info("------------end-------------");

        wrapperResponse.copyBodyToResponse();
    }

    /**
     * 打印请求参数
     * @param request
     */
    private String getRequestBody(ContentCachingRequestWrapper request) {
        ContentCachingRequestWrapper wrapper = WebUtils.getNativeRequest(request, ContentCachingRequestWrapper.class);
        if (wrapper != null) {
            String body = new String(wrapper.getContentAsByteArray());
            return pattern.matcher(body).replaceAll("");
        }
        return "";
    }

    /**
     * 打印返回参数
     * @param response
     */
    private String getResponseBody(ContentCachingResponseWrapper response) {
        ContentCachingResponseWrapper wrapper = WebUtils.getNativeResponse(response, ContentCachingResponseWrapper.class);
        if (wrapper != null) {
            String body = new String(wrapper.getContentAsByteArray());
            return pattern.matcher(body).replaceAll("");
        }
        return "";
    }

    /**
     * 获取请求地址上的参数
     * @param request
     * @return
     */
    public static String getRequestParams(HttpServletRequest request) {
        StringBuilder sb = new StringBuilder();
        Enumeration<String> enu = request.getParameterNames();
        //获取请求参数
        while (enu.hasMoreElements()) {
            String name = enu.nextElement();
            sb.append(name + "=").append(request.getParameter(name));
            if (enu.hasMoreElements()) {
                sb.append(", ");
            }
        }
        return sb.toString();
    }
}
